$(function () {
    /**
     * @author Nicolas Barradeau
     * http://en.nicoptere.net
     */
    (function () {
        var c;
        var ctx;
        var width;
        var height;

        var axes = [];
        var wanderers = [];
        var colors = [
            "#FFCC00",
            "#66CCF0",
            "#FF0033",
            "#99CC33"
        ];

        window.onload = function () {

            c = document.getElementById("canvas");
            c.width = window.innerWidth
            c.width = window.innerHeight
            ctx = c.getContext("2d");
            window.onresize = onResize;
            window.onmousedown = onMouseDown;
            onResize();
            update()

        }

        function onResize(e) {

            reset();

        }

        function getWidth(element) {
            return Math.max(element.scrollWidth, element.offsetWidth, element.clientWidth);
        }

        function getHeight(element) {
            return Math.max(element.scrollHeight, element.offsetHeight, element.clientHeight);
        }

        function reset() {
            axes = [];

            width = c.width = window.innerWidth
            height = c.height = window.innerHeight

            var random = 500;

            var cols = 30;
            for (var i = 0; i < cols; i++) {
                var a = new point(width / cols * i + random * Math.random(), 0);
                var b = new point(width / cols * i + random * Math.random(), height);
                axes.push(new Axe(a, b));
            }

            var rows = 20;
            for (var i = 0; i < rows; i++) {
                var a = new point(0, height / rows * i + random * Math.random());
                var b = new point(width, height / rows * i + random * Math.random());
                axes.push(new Axe(a, b));
            }
            wanderers = [];
            for (var i = 0; i < colors.length * 3; i++) {
                wanderers.push(new wanderer(Math.random() * width, Math.random() * height,
                    0,
                    Math.random() + .5, colors[i % colors.length]));
            }

        }

        function onMouseDown() {
            // reset();
        }

        function update() {
            requestAnimationFrame(update)
            ctx.fillStyle = "rgba(255,255,255,.25)";
            ctx.globalCompositeOperation = "lighten";
            ctx.fillRect(0, 0, width, height);
            ctx.globalCompositeOperation = "source-over";

            ctx.strokeStyle = "rgba(16,16,16,.01 )";
            for (var j = 0; j < axes.length; j++) axes[j].draw(ctx);

            for (var i = 0; i < wanderers.length; i++) {

                var hull = [];
                var pp_hull = [];
                var p = wanderers[i];
                p.update(width, height);

                ctx.beginPath();

                ctx.fillStyle = p.color;
                ctx.arc(p.x, p.y, 8, 0, Math.PI * 2, true);
                ctx.fill();

                ctx.closePath();

                for (var j = 0; j < axes.length; j++) {

                    var axe = axes[j];

                    var r = axe.reflect(p);

                    ctx.beginPath();

                    ctx.fillStyle = p.color;
                    ctx.arc(r.x, r.y, 2, 0, Math.PI * 2, true);
                    ctx.fill();

                    ctx.closePath();

                }
            }
        }

        var Axe = function (a, b) {
            this.a = a;
            this.b = b;
        }
        Axe.prototype =
            {
                draw: function (ctx) {
                    ctx.beginPath();
                    ctx.moveTo(this.a.x, this.a.y);
                    ctx.lineTo(this.b.x, this.b.y);
                    ctx.stroke();
                    ctx.closePath();
                }
                , reflect: function (p) {
                    return utils.reflect(p, this.a, this.b);
                }
            }

        var wanderer = function (x, y, a, s, color) {
            this.x = x || 0;
            this.y = y || 0;
            this.a = a || 0;
            this.s = s || 1;
            this.color = color || "#000";
        }
        wanderer.prototype =
            {
                update: function (width, height) {
                    with (this) {
                        a += (Math.random() - .5) * 10 / 180 * Math.PI;

                        x += Math.cos(a) * s;
                        y += Math.sin(a) * s;

                        if (x < 0
                            || y < 0
                            || x > width
                            || y > height) a += Math.PI / 180;
                    }
                }
            }

        var point = function (x, y) {
            this.x = x || 0;
            this.y = y || 0;
        }
        var utils = function () {
        };
        utils.reflect = function (p, a, b) {
            var pp = utils.project(p, a, b, false);
            return new point(p.x + (pp.x - p.x) * 2, p.y + (pp.y - p.y) * 2);
        }
        utils.project = function (p, a, b, asSegment) {
            var dx = b.x - a.x;
            var dy = b.y - a.y;
            if (asSegment && dx == 0 && dy == 0) {
                return a;
            }
            var t = ((p.x - a.x) * dx + (p.y - a.y) * dy) / (dx * dx + dy * dy);
            if (asSegment && t < 0) return a;
            if (asSegment && t > 1) return b;
            return new point(a.x + t * dx, a.y + t * dy);
        }

    })();

})